var a = 1 // a会绑定到window上 用let声明不会
function fn(name) {
  console.log(this.a) // window.a
  console.log(name)
}

let obj = {
  a:2
}

// apply 的实现方法就是把参数改成(target, args) 因为apply传递的参数是数组 而call是一个一个的传
// bind 就是返回一个函数
Object.prototype.myCall = function (target, ...args) {
  // 1.判断target
  target = target || window
  // 2.创建唯一属性 防止对象里面本来就有这个属性
  let pro = Symbol()
  // 3.this就是该函数(调用myCall的函数) 这里是fn
  target[pro] = this
  // 4.获得调用的结果 就是调用函数 在对象里面执行,this就指向了对象
  let res = target[pro](...args)
  // 5.删除给对象添加的方法
  delete target[pro]
  // 6.返回结果
  return res
}

Object.prototype.myApply = function (target, args) {
  target = target || window
  let pro = Symbol()
  target[pro] = this
  let res = target[pro](...args)
  delete target[pro]
  return res
}

Object.prototype.myBind = function (target, ...args) {
  target = target || window
  let pro = Symbol()
  target[pro] = this
  return () => {
    const res = target[pro](...args)
    delete target[pro]
    return res
  }
}

// this指向window
fn('1jack')
// 改变this指向为obj
fn.call(obj, '2jack')
fn.myCall(obj, '3jack')
fn.myApply(obj, ['4jack'])
fn.myBind(obj, '5jack')()
